﻿using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace MvcPipe
{
    public static class PipeletHtmlHelperExtensions
    {
        public static void PipeletReferenceCss( this HtmlHelper htmlHelper,string styleSheetUrl,string media = null )
        {
            Contract.Requires<ArgumentNullException>( htmlHelper != null,"htmlHelper");
            Contract.Requires<ArgumentException>( !string.IsNullOrWhiteSpace(styleSheetUrl),"styleSheetUrl");

            var cssReference = new PipeletCssReference()
            {
                Media   = string.IsNullOrWhiteSpace(media) ? "screen" : media, 
                Url     = styleSheetUrl
            };

            var cssReferenceList = htmlHelper.ViewContext.HttpContext.Items[PipeletActionInvoker.CssReferencesHttpContextItemName] as List<PipeletCssReference> ?? new List<PipeletCssReference>();
            
            if ( !cssReferenceList.Any(c => c.Url.Equals(styleSheetUrl,StringComparison.OrdinalIgnoreCase)) )
            {
                cssReferenceList.Add(cssReference);
                htmlHelper.ViewContext.HttpContext.Items[PipeletActionInvoker.CssReferencesHttpContextItemName] = cssReferenceList;
            }
        }

        public static void PipeletReferenceJavascript( this HtmlHelper htmlHelper,string javascriptUrl )
        {
            Contract.Requires<ArgumentNullException>(htmlHelper != null, "htmlHelper");
            Contract.Requires<ArgumentException>(!string.IsNullOrWhiteSpace(javascriptUrl), "javascriptUrl");

            var javascriptReferenceList = htmlHelper.ViewContext.HttpContext.Items[PipeletActionInvoker.JavascriptReferencesHttpContextItemName] as List<string> ?? new List<string>();

            if ( !javascriptReferenceList.Any(j => j.Equals(javascriptUrl,StringComparison.OrdinalIgnoreCase)) )
            {
                javascriptReferenceList.Add(javascriptUrl);
                htmlHelper.ViewContext.HttpContext.Items[PipeletActionInvoker.CssReferencesHttpContextItemName] = javascriptReferenceList;
            }
        }

        public static IHtmlString PipeletPlaceHolders( this HtmlHelper htmlHelper,IEnumerable<PipeletDescription> pipelets = null,object htmlAttributes = null )
        {
            Contract.Requires<ArgumentNullException>( htmlHelper != null,"htmlHelper");

            pipelets = pipelets ?? htmlHelper.ViewData.Model as IEnumerable<PipeletDescription>;

            if ( pipelets == null )
            {
                throw new ArgumentNullException("pipelets","pipelets must either be passed to the html helper, or be the model type of the view");
            }

            return
                new MvcHtmlString(pipelets.Select(p => PipeletPlaceHolder(htmlHelper, p,htmlAttributes).ToString()).Aggregate(
                    (current, next) => current + next));
        }

        public static IHtmlString PipeletPlaceHolder( this HtmlHelper htmlHelper,PipeletDescription pipeletDescription,object htmlAttributes = null )
        {
            Contract.Requires<ArgumentNullException>( htmlHelper != null,"htmlHelper");

            var tagBuilder = new TagBuilder("div");
            if (htmlAttributes != null)
            {
                tagBuilder.MergeAttributes(new RouteValueDictionary(htmlAttributes));
            }

            tagBuilder.Attributes["id"] = pipeletDescription.Name;

            return new MvcHtmlString(tagBuilder.ToString(TagRenderMode.Normal));
        }

        public static IHtmlString PipeletBootstrapScript( this HtmlHelper htmlHelper )
        {
            Contract.Requires<ArgumentNullException>( htmlHelper != null,"htmlHelper");

            using( var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("MvcPipe.MvcPipe.min.js"))
            {
                var reader = new StreamReader(stream);
                return new MvcHtmlString(reader.ReadToEnd());
            }
        }
    }
}